﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Reflection;
using AppFx.Reflection.Attributes;
using AppFx.ComponentModel.Descriptive;
using System.Globalization;
using AppFx.Data.Sort;
using AppFx.Collections;
using System.IO;
using AppFx.Tokenization;
using System.Diagnostics;
using AppFx.Parsing;
using AppFx.Evaluation;

namespace ConsoleApplication1
{
	class Program
	{
		static void Main(string[] args)
		{
            ITokenizer tokenizer = new ExpressionTokenizer();

            List<string> Expressions = new List<string>();
            Expressions.Add("true & !false");
            Expressions.Add("1 <> 2 & 3 != 4");
            Expressions.Add("PI + 2 * 4");
            Expressions.Add("1 + 2");
            Expressions.Add("'abc' 'def'");
            Expressions.Add("'abc' 95801 'def' 56798");
            Expressions.Add("9587 + 851 - 759 * 2 / 6");
            Expressions.Add("(-9,587 + 8.515.515) - A75.933.221.321,58 * +2 / 6,9");
            Expressions.Add("-9,587 + 8.515.515 - A75.933.221.32.1,58 * +2 / 6,9");
            Expressions.Add("true false + 5 / 5,2");
            Expressions.Add("9 * 1 + 3 / 4");
            Expressions.Add("909 * 10 + 3 / 45");
            Expressions.Add("90,9 * 1,0 + 3 / 4.5");
            Expressions.Add("1 / 2");
            Expressions.Add("1 * 2");
            Expressions.Add("true | false + 5 / 5,2");

            //ManTest(tokenizer);

            Print(tokenizer, Expressions);

            //for(int i = 0; i < 5; i++)
            //    Perf(tokenizer, Expressions, 1000);
		}

        static void Perf(ITokenizer tokenizer, List<string> Expressions, int iterations)
        {
            List<long> times = new List<long>();
            int tkCount = 0;
            for (int i = 0; i < iterations; i++)
            {
                IEnumerable<IToken> result = null;
                Stopwatch watch = new Stopwatch();

                foreach (string expression in Expressions)
                {
                    watch.Start();
                    result = tokenizer.Tokenize(expression);
                    watch.Stop();
                    times.Add(watch.ElapsedMilliseconds);
                    tkCount += result.Count();
                }
            }
            Console.WriteLine("Tokenizations: {0} @ AVG: {1}MS, Time: {2}, Tokens: {3}", iterations * Expressions.Count, times.Average(), times.Sum(), tkCount);
            Console.ReadLine();
        }

        static void Print(ITokenizer tokenizer, List<string> Expressions)
        {
            Console.WriteLine("-------------------------------");
            foreach (var expression in Expressions)
            {
                Console.WriteLine(expression);
                Console.WriteLine("-------------------------------");
                IList<IToken> tokens = tokenizer.Tokenize(expression).ToList();
                for (int i = 0; i < tokens.Count(); i++)
                {
                    Console.WriteLine("{0} -> {1}", i, tokens[i]);
                }
                Console.WriteLine("-------------------------------");
            }
            Console.ReadLine();
        }

        static void ManTest(ITokenizer tokenizer)
        {
            PreParser parser = new PreParser();
            RpnParser rpnParser = new RpnParser();
            RpnEvaluator eval = new RpnEvaluator();
            DynamicMethodRpnEvaluator dyn = new DynamicMethodRpnEvaluator();

            string input = Console.ReadLine();
            while (input.ToLower() != "exit")
            {
                if (!String.IsNullOrWhiteSpace(input))
                {
                    Console.WriteLine("-------------------------------");
                    Console.WriteLine("-------------INPUT-------------");
                    Console.WriteLine("-------------------------------");
                    Console.WriteLine(input);
                    Console.WriteLine("-------------------------------");
                    Console.WriteLine("-------------TOKEN-------------");
                    Console.WriteLine("-------------------------------");
                    var tokens = tokenizer.Tokenize(input).ToList();
                    for (int i = 0; i < tokens.Count(); i++)
                    {
                        Console.WriteLine("{0} -> {1}", i, tokens[i]);
                    }
                    Console.WriteLine("-------------------------------");
                    Console.WriteLine("-------------PARSD-------------");
                    Console.WriteLine("-------------------------------");
                    var pTokens = parser.Parse(tokens);
                    for (int i = 0; i < pTokens.Count(); i++)
                    {
                        Console.WriteLine("{0} -> {1}", i, pTokens[i]);
                    }
                    Console.WriteLine("-------------------------------");
                    Console.WriteLine("--------------RPN--------------");
                    Console.WriteLine("-------------------------------");
                    var rpnTokens = rpnParser.Parse(pTokens);
                    for (int i = 0; i < rpnTokens.Count(); i++)
                    {
                        Console.WriteLine("{0} -> {1}", i, rpnTokens[i]);
                    }
                    Console.WriteLine("-------------------------------");
                    Console.WriteLine("-------------------------------");
                    Console.WriteLine("STATIC-RESULT: {0}", eval.EvaluateRpn(rpnTokens));
                    Console.WriteLine("-------------------------------");
                    Console.WriteLine("-------------------------------");
                    Console.WriteLine("COMPIL-RESULT: {0}", dyn.Create(rpnTokens));
                    Console.WriteLine("-------------------------------");
                    Console.WriteLine("-------------------------------");
                }
                input = Console.ReadLine();
            }
            Console.WriteLine("END");
        }
	}
}
